package _08_blocking_queue;


import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author: mornd
 * @dateTime: 2023/6/8 - 22:58
 */
public class ThreadUnsafeTest {
    public static void main(String[] args) throws Exception {
        Queue queue = new Queue(2);
        queue.offer(1);
        queue.offer(2);
        Thread t1 = new Thread(() -> {
            try {
                queue.offer(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, "t1");
        t1.setPriority(1);
        t1.start();

        Thread t2 = new Thread(() -> {
            try {
                queue.offer(4);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, "t2");
        t2.start();

        Thread t3 = new Thread(() -> {
            try {
                queue.poll();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, "t3");
        t3.setPriority(10);
        t3.start();

        t1.join();
        t2.join();
        System.out.println(queue);
    }

    private static class Queue {
        int[] arr;
        int size;
        int tail;

        public Queue(int capacity) {
            arr = new int[capacity];
        }

        ReentrantLock lock = new ReentrantLock();
        Condition tailWaits = lock.newCondition();

        public void offer(int i) throws InterruptedException {
//            lock.lock();
            lock.lockInterruptibly(); // 线程在阻塞时可以被打断
            try {
                while (isFull()) {
                    tailWaits.await(); // 释放锁，进行等待，被唤醒后会重新争夺锁，得到锁后进行执行，否则继续阻塞最终获得到锁
                    System.out.println();
                }
                arr[tail++] = i;
                if (tail == arr.length) {
                    tail = 0;
                }
                size++;
            } finally {
                lock.unlock();
            }
        }

        public int poll() throws InterruptedException {
            int i = arr[--size];
            arr[size] = -1;

            lock.lockInterruptibly();
            try {
                tailWaits.signal(); // 需等到解锁（unlock方法调用）才会真正唤醒一个await的线程
            } finally {
                lock.unlock();
            }
            return i;
        }

        public boolean isFull() {
            return size == arr.length;
        }

        @Override
        public String toString() {
            return Arrays.toString(arr) + "  size=" + size;
        }
    }
}
